using System;
using System.Linq;
using System.Collections.Generic;

namespace Test.ConsoleProgram.Algorithm.Solution
{
    [TestDescription("算法: 0125. 验证回文串")]
    public class No0125_IsPalindrome : AbsBaseTestItem
    {
        public override void OnTest()
        {
            Assert.TestExe(IsPalindrome, (string)null, true);
            Assert.TestExe(IsPalindrome, string.Empty, true);
            Assert.TestExe(IsPalindrome, "A man, a plan, a canal: Panama", true);
            Assert.TestExe(IsPalindrome, "race a car", false);

            Assert.TestExe(IsPalindrome2, (string)null, true);
            Assert.TestExe(IsPalindrome2, string.Empty, true);
            Assert.TestExe(IsPalindrome2, "A man, a plan, a canal: Panama", true);
            Assert.TestExe(IsPalindrome2, "race a car", false);

            Assert.TestExe(IsPalindrome3, (string)null, true);
            Assert.TestExe(IsPalindrome3, string.Empty, true);
            Assert.TestExe(IsPalindrome3, "A man, a plan, a canal: Panama", true);
            Assert.TestExe(IsPalindrome3, "race a car", false);
        }
        public bool IsPalindrome(string s)
        {
            if (string.IsNullOrEmpty(s))
            {
                return true;
            }
            var chars = new List<int>();
            for (int i = 0; i < s.Length; i++)
            {
                int c = s[i];
                int n = -1;
                n = 48 <= c && c <= 57 ? c - 48 : n;
                n = 65 <= c && c <= 90 ? c - 55 : n;
                n = 97 <= c && c <= 122 ? c - 87 : n;
                if (n > -1)
                {
                    chars.Add(n);
                }
            }
            int len = chars.Count;
            for (int i = 0; i < len; i++)
            {
                if (chars[i] != chars[len - 1 - i])
                {
                    return false;
                }
            }
            return true;
        }

        /// <summary>
        /// 双指针方法
        /// </summary>
        public bool IsPalindrome2(string s)
        {
            if (string.IsNullOrEmpty(s))
            {
                return true;
            }

            int ToInt(char c)
            {
                int n = -1;
                n = 48 <= c && c <= 57 ? c - 48 : n;
                n = 65 <= c && c <= 90 ? c - 55 : n;
                n = 97 <= c && c <= 122 ? c - 87 : n;
                return n;
            };

            int l = 0, r = s.Length - 1;
            int ln = 0;
            int rn = 0;
            while (l < r)
            {
                while (l < r)
                {
                    ln = ToInt(s[l]);
                    if (ln > -1) break;
                    l++;
                }
                while (l < r)
                {
                    rn = ToInt(s[r]);
                    if (rn > -1) break;
                    r--;
                }
                if (l < r)
                {
                    if (ln != rn) return false;
                    l++;
                    r--;
                }
            }
            return true;
        }

        /// <summary>
        /// 双指针方法, 大神漂亮的代码
        /// </summary>
        public bool IsPalindrome3(string s)
        {
            if (string.IsNullOrEmpty(s))
            {
                return true;
            }
            int l = 0, r = s.Length - 1;
            while (l < r)
            {
                if (!char.IsLetterOrDigit(s[l]))
                {
                    l++;
                    continue;
                }
                if (!char.IsLetterOrDigit(s[r]))
                {
                    r--;
                    continue;
                }
                if (char.ToLower(s[l]) != char.ToLower(s[r]))
                {
                    return false;
                }
                l++;
                r--;
            }
            return true;
        }
    }
}
